//  Vitamin Balance
// 题目：有N种食物，每种食物含有维生素1、2、3中的一种
// 每种食物提供Ai单位的维生素Vi，消耗Ci卡路里
// 在总卡路里不超过X的条件下，选择食物子集
// 目标是最大化三种维生素摄入量的最小值

#include <bits/stdc++.h>

using namespace std;
constexpr int inf = 1e9;

int main() {
  int n, X, K = 3;
  cin >> n >> X;

  // 按维生素类型分组存储食物信息
  // v[i]存储第i种维生素对应的食物列表，每个元素是(卡路里, 维生素量)
  vector<vector<pair<int, int>>> v(3);
  for (int i = 0; i < n; i++) {
    int a, b, c;
    cin >> a >> b >> c; // a:维生素类型(1-3), b:维生素量, c:卡路里
    --a;                // 转换为0-based索引
    v[a].emplace_back(c, b);
  }

  // f[i][j]表示对于第i种维生素，使用j卡路里能获得的最大维生素量
  vector<vector<int>> f(K + 1, vector<int>(X + 1, 0));

  // 对每种维生素分别进行0-1背包计算
  for (int i = 0; i < K; i++) {
    auto &g = f[i]; // 当前维生素的DP数组

    // 0-1背包：对于当前维生素的每种食物
    for (auto [cost, val] : v[i]) {
      // 逆序遍历卡路里，确保每个食物只被选择一次
      for (int j = X; j >= cost; j--) {
        g[j] = max(g[j], g[j - cost] + val);
      }
    }
  }

  int ans = 0;
  // 枚举三种维生素分别分配多少卡路里
  // i: 维生素1分配的卡路里
  // j: 维生素2分配的卡路里
  // k = X-i-j: 维生素3分配的卡路里
  for (int i = 0; i <= X; i++) {
    for (int j = 0; j + i <= X; j++) {
      int k = X - i - j;
      // 计算当前分配方案下三种维生素的最小摄入量
      // 并更新全局最大值
      ans = max(ans, min(f[0][i], min(f[1][j], f[2][k])));
    }
  }

  cout << ans << endl;
  return 0;
}